require "quik_start/version"
require 'curb'
require 'zip/zip'

module QuikStart
  
  def self.install(lib_name)
    @installed = [] if @installed == nil
    resolve(lib_name) unless @installed.include?(lib_name)
    @installed
  end
  
  def self.check_listing(lib_name)
    puts "  --> "+lib_name.to_s + " not in QuikStart" if libraries[lib_name].nil?
  end
  
  def self.check_dependencies(lib_name)
    if libraries[lib_name] != nil && libraries[lib_name][:dependencies]
      libraries[lib_name][:dependencies].each do |d|
        install(d) 
      end
    end
  end
  
  def self.resolve(lib_name)
    check_listing(lib_name)
    check_dependencies(lib_name)
    @installed << lib_name
    puts '  resolving ' + lib_name.to_s unless libraries[lib_name].nil?
  end
  
  def self.log_duration(start_time)
    duration = Time.now - start_time
    puts "  "+duration.to_s + ' seconds'
  end
  
  def self.download_all(platform, libs)
    puts '  downloading...'
    to_install = []
    libs.keys.each do |l|
      lib = QuikStart.libraries[l][:development]
      to_install << lib if lib != nil
    end
    
    libs.keys.each do |l|
      lib = QuikStart.libraries[l][:package]
      to_install << lib if lib != nil
    end
    
    responses = {}
    requests = to_install.uniq
    m = Curl::Multi.new
    requests.each do |url|
      responses[url] = ""
      c = Curl::Easy.new(url) do|curl|
        curl.follow_location = true
        curl.on_body{|data| responses[url] << data; data.size }
        curl.on_success {|easy|  }
      end
      m.add(c)
    end

    m.perform do
      # puts "."
    end

    
    libs.keys.each do |l|
      file_name = QuikStart.libraries[l][:target]
      if QuikStart.libraries[l][:development]
        File.open(File.expand_path('.') + QuikStart.asset_path(platform) + file_name, 'w') do |f2|
          f2.puts responses[QuikStart.libraries[l][:development]]
        end
      else
        File.open(File.expand_path('.') + QuikStart.asset_path(platform)+ file_name, 'w') do |f2|
          f2.puts responses[QuikStart.libraries[l][:package]]
        end
        unzip(platform, File.expand_path('.') + QuikStart.asset_path(platform) + file_name)
      end
    end
    puts
    write_asset_files(platform, libs.keys)
  end
  
  def self.asset_path(platform)
    if platform == :rails
      '/app/assets' 
    elsif platform == :node
      '/public' 
    end
  end
  
  def self.unzip(platform, file)
    Zip::ZipFile.open(file) do |zipfile|
      zipfile.each do |entry|
        if File.extname(entry.name) == '.js'
          File.open(File.expand_path('.') + QuikStart.asset_path(platform) + '/javascripts/' + File.basename(entry.name), 'w') do |f2|
            f2.puts entry.get_input_stream.read
          end
        end
        if File.extname(entry.name) == '.css'
          File.open(File.expand_path('.') + QuikStart.asset_path(platform) + '/stylesheets/' + File.basename(entry.name), 'w') do |f2|
            f2.puts entry.get_input_stream.read
          end
        end
      end
    end
    File.delete(file)
  end
  
  def self.analyze(to_install)
    assets = {}
    to_install.each do |lib_name|
      if assets[lib_name] == nil
        QuikStart.install(lib_name).each do |installed|
          assets[installed] = true
        end
      end
    end
    assets
  end
  
  def self.write_asset_files(platform, installed=[])
    write_css_file(platform, installed)
    write_js_file(platform, installed)
  end
  
  def self.write_css_file(platform, installed)
    if platform == :rails
      puts
      if installed.include?(:bootstrap)
        puts 'puts the following in your application.css file: '
        puts ' *= require "bootstrap" '
        puts
      end
    end
  end
  
  def self.write_js_file(platform, installed)
    if platform == :rails
      puts
      puts 'puts the following in your application.js file: '
      installed.each do |i|
        puts ' //= require '+ i.to_s
      end
      puts
    end
  end
  
  def self.libraries
    {
      :backbone => { 
        :development => 'http://backbonejs.org/backbone.js', 
        :production => 'http://backbonejs.org/backbone-min.js',
        :dependencies => [:underscore, :json2],
        :target => '/javascripts/backbone.js'
      },
      :bootstrap => {
        :package => 'http://twitter.github.com/bootstrap/assets/bootstrap.zip',
        :dependencies => [:jquery],
        :extraction_method => :extract_bootstrap,
        :target => '/javascripts/bootstrap.zip'
      },
      :underscore => {
        :development => 'http://underscorejs.org/underscore.js', 
        :production => 'http://underscorejs.org/underscore-min.js',
        :target => '/javascripts/underscore.js'
      },
      :json2 => {
        :development => 'https://raw.github.com/douglascrockford/JSON-js/master/json2.js', 
        :production => 'https://raw.github.com/douglascrockford/JSON-js/master/json2.js',
        :target => '/javascripts/json2.js'
      },
      :jqueryui => {
        :production => 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js',
        :development => 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.js',
        :dependencies => [:jquery],
        :target => '/javascripts/jquery-ui.js'
      },
      :marionette => {
        :production => 'http://marionettejs.com/downloads/backbone.marionette.min.js',
        :development => 'http://marionettejs.com/downloads/backbone.marionette.js',
        :dependencies => [:backbone, :underscore, :jquery, :json2, :wreqr, :babysitter],
        :target => '/javascripts/marionette.js'
      },
      :wreqr => {
        :production => 'https://raw.github.com/marionettejs/backbone.wreqr/master/lib/backbone.wreqr.js',
        :development => 'https://raw.github.com/marionettejs/backbone.wreqr/master/lib/backbone.wreqr.js',
        :dependencies => [:backbone],
        :target => '/javascripts/wreqr.js'
      },
      :babysitter => {
        :production => 'https://raw.github.com/marionettejs/backbone.babysitter/master/lib/backbone.babysitter.js',
        :development => 'https://raw.github.com/marionettejs/backbone.babysitter/master/lib/backbone.babysitter.js',
        :dependencies => [:backbone],
        :target => '/javascripts/babysitter.js'
      },
      :jquery => {
        :production => 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
        :development => 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js',
        :target => '/javascripts/jquery.js'
      },
      :angular => {
        :development => 'https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js',
        :production => 'https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js',
        :target => '/javascripts/angular.js'
      },
      :d3 => {
        :production => 'https://raw.github.com/mbostock/d3/master/d3.min.js',
        :development => 'https://raw.github.com/mbostock/d3/master/d3.js',
        :target => '/javascripts/d3.js'
      },
      :taffy => {
        :production => 'https://raw.github.com/typicaljoe/taffydb/master/taffy-min.js',
        :development => 'https://raw.github.com/typicaljoe/taffydb/master/taffy.js',
        :target => '/javascripts/taffy.js'
      },
      :wysihtml5 => {
        :development => 'https://raw.github.com/xing/wysihtml5/master/dist/wysihtml5-0.3.0.js',
        :production => 'https://raw.github.com/xing/wysihtml5/master/dist/wysihtml5-0.3.0.min.js',
        :target => '/javascripts/wysihtml5.js'
      },
      :zepto => {
        :development => 'http://zeptojs.com/zepto.js',
        :production => 'http://zeptojs.com/zepto.min.js',
        :target => '/javascripts/zepto.js'
      },
      :lunr => {
        :development => 'https://raw.github.com/olivernn/lunr.js/master/lunr.js',
        :production => 'https://raw.github.com/olivernn/lunr.js/master/lunr.min.js',
        :target => '/javascripts/lunr.js'
      },
      :augment => {
        :development => 'https://raw.github.com/olivernn/augment.js/master/augment.js',
        :production => 'https://raw.github.com/olivernn/augment.js/master/augment.min.js',
        :target => '/javascripts/augment.js'
      }
    }
  end
end
